package com.darin.cl.task;

import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

/**
 * 简单Task实现.<br>
 * 
 * @param <Params>参数
 * @param <Progress>进度
 * @param <Result>结果
 * @author Jianfeng.Lao
 * @version 1.0
 * @CreateDate 2013-10-29
 */
public abstract class CLTask<Params, Progress, Result> {
	private static final String TAG = "CLTask";
	private Params[] mParams;
	private String mName;
	private boolean isCancel = false;
	private CLTaskCallable mCLTaskCallable;
	private CLFutureTask mCLFutureTask;
	private volatile Status mStatus = Status.PENDING;

	public enum Status {
		/**
		 * Task准备工作.
		 */
		PENDING,
		/**
		 * Task进行工作中.
		 */
		RUNNING,
		/**
		 * Task结束.
		 * 
		 */
		FINISHED,
	}

	private static final int MSG_UPDATE_PROGRESS = 0x11000001;
	private static final int MSG_ON_EXCEPTION = 0x11000002;
	private static final int MSG_ON_PRE_EXECUTE = 0x11000003;
	private static final int MSG_ON_SUCCESS = 0x11000004;
	private static final int MSG_ON_CANCEL = 0x11000005;
	private static final int MSG_ON_FINISHED = 0x11000006;

	private Handler mCallBackHandle = new Handler(Looper.getMainLooper()) {

		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			Object obj = msg.obj;
			switch (msg.what) {
			case MSG_UPDATE_PROGRESS:
				onProgressUpdate((Progress[]) msg.obj);
				break;
			case MSG_ON_EXCEPTION:
				doOnException((Exception) obj);
				break;
			case MSG_ON_PRE_EXECUTE:
				onPreExecute();
				break;
			case MSG_ON_SUCCESS:
				doOnSuccess((Result) obj);
				break;
			case MSG_ON_CANCEL:
				onCanceled();
				break;
			case MSG_ON_FINISHED:
				onFinish();
				break;
			}
		}

	};

	public CLTask() {
	}

	/**
	 * 重新设置Task
	 * 
	 * @author Jianfeng.Lao
	 * @CreateDate 2013年11月15日
	 */
	public void reset() {
		isCancel=false;
		mName="CLTask_"+System.currentTimeMillis();
		mStatus = Status.PENDING;
		mCLTaskCallable = new CLTaskCallable();
		mCLFutureTask = new CLFutureTask(mCLTaskCallable);
	}

	public Params[] getParams() {
		return mParams;
	}

	public void setParams(Params... params) {
		this.mParams = params;
	}

	public boolean isCancel() {
		return isCancel;
	}

	public String getName() {
		return mName;
	}

	/**
	 * 准备执行Task
	 * 
	 * @author Jianfeng.Lao
	 * @CreateDate 2013年11月15日
	 */
	protected void onPreExecute() {
	};

	/**
	 * 更新进度
	 * 
	 * @param progress
	 * @author "Jianfeng.Lao"
	 * @CreateDate 2013年11月15日
	 */
	protected void onProgressUpdate(Progress... progress) {
	};

	/**
	 * 异步处理方法,做非UI线程工作
	 * 
	 * @param params
	 * @return
	 * @throws Exception
	 * @author Jianfeng.Lao
	 * @CreateDate 2013年11月15日
	 */
	public abstract Result doInBackground(Params... params) throws Exception;

	/**
	 * 异步处理无异常下回调方法,通知Task成功完成
	 * 
	 * @param result
	 * @author Jianfeng.Lao
	 * @CreateDate 2013年11月15日
	 */
	public abstract void doOnSuccess(Result result);

	/**
	 * 调用{@link #cancel()}通知状态方法
	 * 
	 * @author Jianfeng.Lao
	 * @CreateDate 2013年11月15日
	 */
	protected void onCanceled() {
	}

	/**
	 * 通知Task结束
	 * 
	 * @author Jianfeng.Lao
	 * @CreateDate 2013-10-29
	 */
	protected void onFinish() {
	};

	/**
	 * 如果异步处理过程中{@link #doInBackGround(Object...)}抛出Exception的情况下,并且{@link #handlerException(Exception)}返回true和
	 * {@link #ignoreException(Exception)}返回false,回调些方法.
	 * 
	 * @param exception
	 * @author Jianfeng.Lao
	 * @CreateDate 2013-10-29
	 * 
	 * @see #ignoreException(Exception)
	 * @see #handlerException(Exception)
	 */
	protected void doOnException(Exception exception) {
	}

	/**
	 * 用于判断exception是否自行处理
	 * 
	 * @param exception
	 * @return 如果返回true,并且 {@link #ignoreException(Exception)}返回false,这种状态下会调用 {@link #doOnException(Exception)}. 否则会调用
	 *         {@link #onCanceled()}
	 * @author Jianfeng.Lao
	 * @CreateDate 2013-10-29
	 * 
	 * @see #ignoreException(Exception)
	 * @see #doOnException(Exception)
	 */
	protected boolean handlerException(Exception exception) {
		return exception!=null?true:false;
	}

	/**
	 * 忽略某个Exception
	 * 
	 * @param exception
	 * @return 如果返回true,忽略处理这个Exception
	 * @author Jianfeng.Lao
	 * @CreateDate 2013-10-29
	 * 
	 * @see #doOnException(Exception)
	 * @see #handlerException(Exception)
	 */
	protected boolean ignoreException(Exception exception) {
		boolean result = false;
		if (exception != null) {
			if (exception instanceof CancellationException) {
				result = true;
			} else if (exception instanceof InterruptedException) {
				result = true;
			}
			if (exception.getCause() != null) {
				Throwable throwale = exception.getCause();
				if (throwale instanceof CancellationException) {
					result = true;
				} else if (throwale instanceof InterruptedException) {
					result = true;
				}
			}
		}
		return result;
	}

	public class CLTaskCallable implements Callable<Result> {

		@Override
		public Result call() throws Exception {
			// System.out.println("Task>>" + mName + ",call>>");
			mStatus = Status.RUNNING;
			return doInBackground(mParams);
		}

	}

	public class CLFutureTask extends FutureTask<Result> {

		@Override
		public void run() {
			sendCallBackMsg(MSG_ON_PRE_EXECUTE, null);
			while (true) {
				if (!mCallBackHandle.hasMessages(MSG_ON_PRE_EXECUTE)) {
					// 检查onPreExecute状态是否发出
					super.run();
					break;
				}
			}

		}

		public CLFutureTask(Callable<Result> callable) {
			super(callable);
		}

		@Override
		protected void done() {
			super.done();
			Result result = null;
			Exception throwable = null;
			boolean hasException = false;
			try {
				result = get();
			} catch (InterruptedException e) {
				throwable = e;
				hasException = true;
			} catch (ExecutionException e) {
				throwable = e;
				hasException = true;
			} catch (CancellationException e) {
				throwable = e;
				hasException = true;
			} finally {
				if (throwable != null) {
					throwable.printStackTrace();
				}
				mStatus = Status.FINISHED;
				if (handlerException(throwable) && !ignoreException(throwable)) {
					sendCallBackMsg(MSG_ON_EXCEPTION, throwable);
				} else {
					if (!hasException&&!isCancel) {
						sendCallBackMsg(MSG_ON_SUCCESS, result);
					} else {
						sendCallBackMsg(MSG_ON_CANCEL, null);
					}
				}
				sendCallBackMsg(MSG_ON_FINISHED, null);
				// System.out.println(mName + " onFinish>>" + hasException);
			}
			
			
		}

		@Override
		public boolean cancel(boolean mayInterruptIfRunning) {
			Log.v(TAG, "CLTaskCallable >>cancel "+mName);
			isCancel=true;
			beforeCancel();
			return super.cancel(mayInterruptIfRunning);
		}
		
		
		public String getName(){
			return mName;
		}
		
		public Status getStatus(){
			return mStatus;
		}
		
		
		
	}

	CLFutureTask getCLFutureTask() {
		return mCLFutureTask;
	}

	/**
	 * 取消当前Task
	 * 
	 * @author Jianfeng.Lao
	 * @CreateDate 2013-10-29
	 */
	public void cancel(boolean mayInterruptIfRunning) {
		mCLFutureTask.cancel(mayInterruptIfRunning);
	}

	/**
	 * 取消当前Task
	 * 
	 * @author Jianfeng.Lao
	 * @CreateDate 2013-10-29
	 */
	public void cancel() {
		mCLFutureTask.cancel(true);
	}

	/**
	 * 返回当前状态
	 * 
	 * @return
	 * @author Jianfeng.Lao
	 * @CreateDate 2013-10-29
	 */
	public Status getStatus() {
		return mStatus;
	}

	/**
	 * 发送Task状态消息
	 * 
	 * @param what
	 * @param data
	 * @author Jianfeng.Lao
	 * @CreateDate 2013年11月15日
	 */
	private void sendCallBackMsg(int what, Object data) {
		mCallBackHandle.obtainMessage(what, data).sendToTarget();
	}

	/**
	 * 通知进度更新,回调{@link #onProgressUpdate(Object...)}
	 * 
	 * @param value
	 * @author Jianfeng.Lao
	 * @CreateDate 2013年11月15日
	 */
	public void publishProgress(Progress... value) {
		sendCallBackMsg(MSG_UPDATE_PROGRESS, value);
	}
	/**
	 * 当调用cancel时调用或者线程池被destory
	 * 
	 * @author Jianfeng.Lao
	 * @CreateDate 2014年3月26日
	 */
	protected void beforeCancel(){
	}

	@Override
	public String toString() {
		return "CLTask [mName=" + mName + ", mStatus=" + mStatus + "]";
	}
	
	

}
